/*************************************************************************
Title:    Interrupt UART library with receive/transmit circular buffers
Author:   Peter Fleury <pfleury@gmx.ch>   http://jump.to/fleury
File:     $Id: uart.c,v 1.6.2.2 2009/11/29 08:56:12 Peter Exp $
Software: AVR-GCC 4.1, AVR Libc 1.4.6 or higher
Hardware: any AVR with built-in UART, 
License:  GNU General Public License 
          
DESCRIPTION:
    An interrupt is generated when the UART has finished transmitting or
    receiving a byte. The interrupt handling routines use circular buffers
    for buffering received and transmitted data.
    
    The UART_RX_BUFFER_SIZE and UART_TX_BUFFER_SIZE variables define
    the buffer size in bytes. Note that these variables must be a 
    power of 2.
    
USAGE:
    Refere to the header file uart.h for a description of the routines. 
    See also example test_uart.c.

NOTES:
    Based on Atmel Application Note AVR306
                    
LICENSE:
    Copyright (C) 2006 Peter Fleury

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
                        
*************************************************************************/
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include "uart.h"

/*
 *  constants and macros
 */

/* size of RX/TX buffers */
#define UART_RX_BUFFER_MASK ( UART_RX_BUFFER_SIZE - 1)
#define UART_TX_BUFFER_MASK ( UART_TX_BUFFER_SIZE - 1)


/*
 *  module global variables
 */
static volatile unsigned char UART_TxBuf[UART_TX_BUFFER_SIZE];
static volatile unsigned char UART_RxBuf[UART_RX_BUFFER_SIZE];
static volatile unsigned char UART_TxHead;
static volatile unsigned char UART_TxTail;
static volatile unsigned char UART_RxHead;
static volatile unsigned char UART_RxTail;
static volatile unsigned char UART_LastRxError;



ISR(USART1_RX_vect)
/*************************************************************************
Function: UART Receive Complete interrupt
Purpose:  called when the UART has received a character
**************************************************************************/
{
//    unsigned char tmphead;
//    unsigned char data;
//    unsigned char usr;
//    unsigned char lastRxError;
//
//
//    /* read UART status register and UART data register */
//    usr  = UCSR1A;
//    data = UDR1;
//
//    /* */
//
//    lastRxError = (usr & (_BV(FE)|_BV(DOR)) );
//
//
//    /* calculate buffer index */
//    tmphead = ( UART_RxHead + 1) & UART_RX_BUFFER_MASK;
//
//    if ( tmphead == UART_RxTail ) {
//        /* error: receive buffer overflow */
//        lastRxError = UART_BUFFER_OVERFLOW >> 8;
//    }else{
//        /* store new index */
//        UART_RxHead = tmphead;
//        /* store received data in buffer */
//        UART_RxBuf[tmphead] = data;
//    }
//    UART_LastRxError = lastRxError;
}


//ISR(USART1_TX_vect)
ISR(USART1_UDRE_vect)
/************************************************************************
Function: UART Data Register Empty interrupt
Purpose:  called when the UART is ready to transmit the next byte
*************************************************************************/
{
	unsigned char tmptail;

	if (UART_TxHead != UART_TxTail)
	{
		//  calculate and store new buffer index
		tmptail = (UART_TxTail + 1) & UART_TX_BUFFER_MASK;
		UART_TxTail = tmptail;
		//  get one byte from buffer and write it to UART
		UDR1 = UART_TxBuf[tmptail]; //  start transmission
	}
	else
	{
		//  tx buffer empty, disable UDRE interrupt
		Uart_disable_data_register_empty_interrupt();
	}
}


/*************************************************************************
Function: usart0_disable()
Purpose:  shutdown UART
Input:    
Returns:  none
**************************************************************************/
void usart1_disable()
{
	UCSR1B &= ~((1<<RXCIE1)|(1<<RXEN1)|(1<<TXEN1));	// schaltet USART Transmitter/Receiver und Complete Interrupt aus

	DDRD &= ~(1<<PD2);		// schaltet RXD-Port auf Eingang
	DDRD &= ~(1<<PD3);		// schaltet TXD-Port auf Eingang
}


/*************************************************************************
Function: uart_init()
Purpose:  initialize UART and set baudrate
Input:    baudrate using macro UART_BAUD_SELECT()
Returns:  none
**************************************************************************/
void uart_init()
{
    // baudrate auf 500.000 */
    UBRR1H = 0;
    UBRR1L = 0;

    // controlregister
    //UCSR1A =
    
    // Frame Format: no parity, asynchronous usart, 1 stopbit, 8 bit character size
    UCSR1C |= (1<<UCSZ11);
    UCSR1C |=  (1<<UCSZ10);

    // enable UART receiver and transmmitter and receive complete interrupt
    Uart_enable_transmitter();

    //Uart_enable_tx_complete_interrupt();
    Uart_enable_data_register_empty_interrupt();
    
}/* uart_init */


///*************************************************************************
//Function: uart_getc()
//Purpose:  return byte from ringbuffer
//Returns:  lower byte:  received byte from ringbuffer
//          higher byte: last receive error
//**************************************************************************/
//unsigned int uart_getc(void)
//{
//    unsigned char tmptail;
//    unsigned char data;
//
//
//    if ( UART_RxHead == UART_RxTail ) {
//        return UART_NO_DATA;   /* no data available */
//    }
//
//    /* calculate /store buffer index */
//    tmptail = (UART_RxTail + 1) & UART_RX_BUFFER_MASK;
//    UART_RxTail = tmptail;
//
//    /* get data from receive buffer */
//    data = UART_RxBuf[tmptail];
//
//    return (UART_LastRxError << 8) + data;
//
//}/* uart_getc */


/*************************************************************************
Function: uart_putc()
Purpose:  write byte to ringbuffer for transmitting via UART
Input:    byte to be transmitted
Returns:  none          
*************************************************************************/
void uart_putc(unsigned char data)
{
    unsigned char tmphead;


    tmphead  = (UART_TxHead + 1) & UART_TX_BUFFER_MASK;

    while ( tmphead == UART_TxTail ){
        ;// wait for free space in buffer
    }

    UART_TxBuf[tmphead] = data;
    UART_TxHead = tmphead;

   //  enable UDRE interrupt
    Uart_enable_data_register_empty_interrupt();
}/* uart_putc */


/*************************************************************************
Function: uart_puts()
Purpose:  transmit string to UART
Input:    string to be transmitted
Returns:  none          
**************************************************************************/
void uart_puts(const char *s, uint8_t length)
{
	uint8_t i;
//    while (*s)
//      uart_putc(*s++);
    for(i = 0; i < length; i++)
    {
    	uart_putc(*(s++));
    }
}/* uart_puts */
